package cn.com.libertymutual.sp.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaBuilder.In;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import cn.com.libertymutual.core.redis.util.RedisUtils;
import cn.com.libertymutual.core.util.BeanUtilExt;
import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.util.Current;
import cn.com.libertymutual.core.util.DateUtil;
import cn.com.libertymutual.core.util.StringUtil;
import cn.com.libertymutual.core.util.enums.CoreServiceEnum;
import cn.com.libertymutual.core.util.uuid.UUID;
import cn.com.libertymutual.core.web.ServiceResult;
import cn.com.libertymutual.core.web.util.RequestUtils;
import cn.com.libertymutual.production.dao.nomorcldatasource.PrpdrationMapper;
import cn.com.libertymutual.production.model.nomorcldatasource.Prpdration;
import cn.com.libertymutual.sp.bean.SysOperationLog;
import cn.com.libertymutual.sp.bean.TbSpApplicant;
import cn.com.libertymutual.sp.bean.TbSpApprove;
import cn.com.libertymutual.sp.bean.TbSpExclusiveProduct;
import cn.com.libertymutual.sp.bean.TbSpFlow;
import cn.com.libertymutual.sp.bean.TbSpFlowDetail;
import cn.com.libertymutual.sp.bean.TbSpHotproduct;
import cn.com.libertymutual.sp.bean.TbSpOrder;
import cn.com.libertymutual.sp.bean.TbSpPlan;
import cn.com.libertymutual.sp.bean.TbSpProduct;
import cn.com.libertymutual.sp.bean.TbSpProductConfig;
import cn.com.libertymutual.sp.bean.TbSpSaleLog;
import cn.com.libertymutual.sp.bean.TbSpTopChannelAuthProduct;
import cn.com.libertymutual.sp.bean.TbSpUser;
import cn.com.libertymutual.sp.bean.TbSysHotarea;
import cn.com.libertymutual.sp.dao.ApplicantDao;
import cn.com.libertymutual.sp.dao.ApproveDao;
import cn.com.libertymutual.sp.dao.FlowDao;
import cn.com.libertymutual.sp.dao.FlowDetailDao;
import cn.com.libertymutual.sp.dao.HotProductDao;
import cn.com.libertymutual.sp.dao.OperationLogDao;
import cn.com.libertymutual.sp.dao.ProductConfigDao;
import cn.com.libertymutual.sp.dao.ProductDao;
import cn.com.libertymutual.sp.dao.SpOrderDao;
import cn.com.libertymutual.sp.dao.SpPlanDao;
import cn.com.libertymutual.sp.dao.SpSaleLogDao;
import cn.com.libertymutual.sp.dao.StoreProductDao;
import cn.com.libertymutual.sp.dao.TbSpExclusiveProductDao;
import cn.com.libertymutual.sp.dao.TbSysHotareaDao;
import cn.com.libertymutual.sp.dao.TopChannelAuthProductDao;
import cn.com.libertymutual.sp.dao.UserDao;
import cn.com.libertymutual.sp.dto.CommonRequestDto;
import cn.com.libertymutual.sp.dto.InsureQuery;
import cn.com.libertymutual.sp.dto.PlanDto;
import cn.com.libertymutual.sp.dto.SpPlansResponseDto;
import cn.com.libertymutual.sp.dto.queryplans.CrossSaleKind;
import cn.com.libertymutual.sp.dto.queryplans.CrossSalePlan;
import cn.com.libertymutual.sp.dto.queryplans.InsuredDto;
import cn.com.libertymutual.sp.dto.queryplans.QueryPlansRequestDTO;
import cn.com.libertymutual.sp.dto.queryplans.QueryPlansResponseDTO;
import cn.com.libertymutual.sp.dto.queryplans.QuerySPPlansRequestDTO;
import cn.com.libertymutual.sp.dto.response.ResponseInsureDto;
import cn.com.libertymutual.sp.dto.savePlan.ProposalSaveForRequestDto;
import cn.com.libertymutual.sp.dto.savePlan.PropsalSaveRequestDto;
import cn.com.libertymutual.sp.dto.savePlan.base.AddressBaseDto;
import cn.com.libertymutual.sp.dto.savePlan.base.AgentBaseDto;
import cn.com.libertymutual.sp.dto.savePlan.base.AppliBaseDto;
import cn.com.libertymutual.sp.dto.savePlan.base.InsuredBaseDto;
import cn.com.libertymutual.sp.dto.savePlan.base.ItemKindBaseDto;
import cn.com.libertymutual.sp.dto.savePlan.base.PeriodBaseDto;
import cn.com.libertymutual.sp.service.api.BranchSetService;
import cn.com.libertymutual.sp.service.api.InsureService;
import cn.com.libertymutual.sp.service.api.ProductService;
import cn.com.libertymutual.sp.service.api.ShopService;
import cn.com.libertymutual.sp.service.api.UserService;
import cn.com.libertymutual.sys.bean.SysCodeNode;
import cn.com.libertymutual.sys.bean.SysServiceInfo;
import cn.com.libertymutual.sys.dao.ISysRoleUserDao;
import cn.com.libertymutual.sys.service.api.ISequenceService;

@Service("productService")
@RefreshScope // 刷新配置无需重启服务
public class ProductServiceImpl implements ProductService {

	private Logger log = LoggerFactory.getLogger(getClass());
	@Resource
	private RestTemplate restTemplate;
	@Autowired
	private FlowDao flowDao;
	@Autowired
	private ApproveDao approveDao;
	@Resource
	private RedisUtils redisUtils;
	@Autowired
	private ApplicantDao applicantDao;
	@Autowired
	private ProductConfigDao productConfigDao;
	@Autowired
	private HotProductDao hotProductDao;
	@Autowired
	private SpOrderDao spOrderDao;
	@Autowired
	private ProductDao productDao;
	@Resource
	private BranchSetService branchSetService;// 机构
	@Autowired
	private StoreProductDao storeProductDao;
	@Autowired
	private ISequenceService iSequenceService;
	@Autowired
	private SpPlanDao spPlanDao;
	@Autowired
	private FlowDetailDao flowDetailDao;
	@Autowired
	private ShopService shopService;
	@Autowired
	private ISysRoleUserDao roleUserDao;
	@Autowired
	private OperationLogDao operationLogDao;
	@Autowired
	private TbSpExclusiveProductDao exclusiveProductDao;
	@Autowired
	private TbSysHotareaDao tbSysHotareaDao;
	@Autowired
	private TopChannelAuthProductDao topChannelAuthProductDao;
	@Autowired
	private PrpdrationMapper prpdrationMapper;
	
	@Autowired
	@Qualifier("readJdbcTemplate")
	protected JdbcTemplate readJdbcTemplate;
	
	@Value("${plan.request.consumerid}")
	private String consumerId;

	@Value("${plan.request.operatecode}")
	private String operateCode;

	@Value("${plan.request.usercode}")
	private String userCode;

	@Value("${plan.request.password}")
	private String passWord;
	@Autowired
	private UserService userService;
	@Autowired
	private SpSaleLogDao spSaleLogDao;

	@Autowired
	private UserDao userDao;

	@Autowired
	private InsureService insureService;

	@Override
	public ServiceResult findAreaInfoByName(String region) {
		ServiceResult sr = new ServiceResult();
		TbSysHotarea tbSysHotarea = (TbSysHotarea) redisUtils.get(Constants.BRANCH_AREA_CODE_INFO);
		if (null != tbSysHotarea) {
			sr.setResult(tbSysHotarea);
		} else {
			TbSysHotarea dbtbSysHotarea = tbSysHotareaDao.findByAreaName(region);
			if (dbtbSysHotarea == null) {
				dbtbSysHotarea = tbSysHotareaDao.findByAreaName("重庆");
			}
			redisUtils.set(Constants.BRANCH_AREA_CODE_INFO + region, dbtbSysHotarea);
			sr.setResult(dbtbSysHotarea);
		}
		return sr;
	}

	@Override
	public ServiceResult productFindAll(String region, String type, int pageNumber, int pageSize, String sorttype) {
		ServiceResult sr = new ServiceResult();
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");// 设置日期格式
		String today = df.format(new Date());
		Sort sort = null;
		if ("ASC".equals(sorttype)) {
			sort = new Sort(Direction.ASC, "serialNo");
		} else {
			sort = new Sort(Direction.DESC, "serialNo");
		}

		if ("hot".equals(type)) {// 热门
			sr.setResult(productDao.findHotPro());
//			if (StringUtils.isNotBlank(region)) {
//				TbSysHotarea area = new TbSysHotarea();
//				TbSysHotarea dbarea = (TbSysHotarea) redisUtils.get(Constants.BRANCH_AREA_CODE_INFO);
//				if (null != dbarea) {
//					area = dbarea;
//				} else {
//					area = tbSysHotareaDao.findByAreaName(region);
//					if (area == null) {
//						area = tbSysHotareaDao.findByAreaName("重庆");
//					}
//				}
//				try {
//					sr.setResult(productDao.findHotProduct(df.parse(today), area.getBranchCode()));
//				} catch (ParseException e) {
//					e.printStackTrace();
//				}
//			}
		} else if ("all".equals(type)) {// 全部
			sr.setResult(productDao.findAll(new Specification<TbSpProduct>() {
				@Override
				public Predicate toPredicate(Root<TbSpProduct> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

					List<Predicate> predicate = new ArrayList<Predicate>();
					predicate.add(cb.equal(root.get("isExclusive").as(String.class), "0"));
					predicate.add(cb.equal(root.get("isShow").as(String.class), "1"));
					Predicate s1 = cb.equal(root.get("status").as(String.class), "3");
					Predicate s2 = cb.equal(root.get("status").as(String.class), "1");
					predicate.add(cb.or(s1, s2));
					predicate.add(cb.lessThanOrEqualTo(root.get("startDate").as(String.class), today));
					predicate.add(cb.greaterThanOrEqualTo(root.get("endDate").as(String.class), today));
					Predicate[] pre = new Predicate[predicate.size()];
					return query.where(predicate.toArray(pre)).getRestriction();

				}
			}, PageRequest.of(pageNumber - 1, pageSize, sort)));

		} else {
			log.info("按险种查:" + type);
			sr = getProduct(sort, pageNumber, pageSize, type);
		}
		return sr;
	}

	public ServiceResult getProduct(Sort sort, int pageNumber, int pageSize, String riskCode) {
		ServiceResult sr = new ServiceResult();

		sr.setResult(productDao.findAll(new Specification<TbSpProduct>() {
			@Override
			public Predicate toPredicate(Root<TbSpProduct> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

				List<Predicate> predicate = new ArrayList<Predicate>();
				log.info("riskCode====>:" + riskCode);
				predicate.add(cb.equal(root.get("isExclusive").as(String.class), "0"));
				predicate.add(cb.equal(root.get("riskCode").as(String.class), riskCode));
				predicate.add(cb.equal(root.get("isShow").as(String.class), "1"));
				Predicate s1 = cb.equal(root.get("status").as(String.class), "3");
				Predicate s2 = cb.equal(root.get("status").as(String.class), "1");
				predicate.add(cb.or(s1, s2));
				SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");// 设置日期格式
				String today = df.format(new Date());
				predicate.add(cb.lessThanOrEqualTo(root.get("startDate").as(String.class), today));
				predicate.add(cb.greaterThanOrEqualTo(root.get("endDate").as(String.class), today));
				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		}, PageRequest.of(pageNumber - 1, pageSize, sort)));
		return sr;

	}

	@Override
	public ServiceResult queryPlan(String planId, Integer age, Integer deadLine) {
		// Object redisPlan =
		// redisUtils.get(Constants.SALE_QUERY_PLAN_SAVE+age+":"+deadLine+":"+planId);
		ServiceResult sr = new ServiceResult();
		sr.setFail();
		QueryPlansResponseDTO response = new QueryPlansResponseDTO();
		// if(null == redisPlan){
		String[] planIds = new String[2];
		planIds[0] = planId;
		QuerySPPlansRequestDTO request = new QuerySPPlansRequestDTO("*ZYWX*", age, deadLine, planIds);
		Map map = (Map) redisUtils.get(Constants.SYS_SERVICE_INFO);
		SysServiceInfo sysServiceInfo = (SysServiceInfo) map.get(CoreServiceEnum.QUERY_SPPLANS_URL.getUrlKey());
		request.setPartnerAccountCode(sysServiceInfo.getUserName());
		request.setFlowId(request.getPartnerAccountCode() + new Date().getTime());
		/*
		 * HttpHeaders headers = new HttpHeaders(); headers.add("account-code",
		 * sysServiceInfo.getUserName()); headers.add("request-time", String.valueOf(new
		 * Date().getTime())); headers.add("soa-token",
		 * pwdEncoder.encodePassword(sysServiceInfo.getPassword(), String.valueOf(new
		 * Date().getTime())));
		 */

		HttpEntity<QuerySPPlansRequestDTO> requestEntity = new HttpEntity<QuerySPPlansRequestDTO>(request,
				RequestUtils.genEncryptHttpHeaders(sysServiceInfo.getUserName(), sysServiceInfo.getPassword()));

		response = restTemplate.postForObject(sysServiceInfo.getUrl(), requestEntity, QueryPlansResponseDTO.class);

		// CrossSalePlan savePlans = new CrossSalePlan();
		// List<CrossSaleKind> savekinds = new ArrayList<CrossSaleKind>();
		// List<CrossSaleKind> kinds =
		// response.getPlanLists().get(0).getKinds();
		// for(int i=0;i<kinds.size();i++){
		// CrossSaleKind crSalePlan = new CrossSaleKind();
		// crSalePlan.setBenefitsCode(kinds.get(i).getBenefitsCode());
		// crSalePlan.setCvgCode(kinds.get(i).getCvgCode());
		// crSalePlan.setAdultMax(kinds.get(i).getAdultMax());
		// crSalePlan.setPercentage(kinds.get(i).getPercentage());
		// savekinds.add(crSalePlan);
		// }
		// savePlans.setKinds(savekinds);
		// redisUtils.set(Constants.SALE_QUERY_PLAN_PRICE+age+deadLine+planIds[0],
		// response.getPlanLists().get(0).getPlanPrice());
		redisUtils.set(Constants.SALE_QUERY_PLAN_SAVE + age + ":" + deadLine + ":" + planId, response);
		// System.out.println(redisUtils.get(Constants.SALE_QUERY_PLAN_SAVE+age+deadLine+planId));

		// }else{
		// response = (QueryPlansResponseDTO) redisPlan;
		// }

		if (response.getStatus() != null && response.getStatus()) {
			sr.setSuccess();
			sr.setResult(response.getPlanLists());
		} else {
			sr.setFail();
			sr.setResult(response.getResultMessage());
		}
		return sr;
	}

	/**
	 * 以代理人代码和动态参数形式查询 因子组
	 * @param dto
	 * @return Map<String,Boolean>   key:plansubcode
	 */
	@Override
	public QueryPlansResponseDTO queryPlansByProd(QueryPlansRequestDTO dto){
		
		QueryPlansResponseDTO response=new QueryPlansResponseDTO();
		response.setFlowId(dto.getFlowId());
		response.setPdk(dto.getPdk());
		response.setStatus(false);
		if(null==dto||null==dto.getProducts()||dto.getProducts().length==0){
			response.setResultMessage("ERROR:产品代码不能为空！");
			return response;
		}
		Map<String,Boolean> returnMap= queryPlansubcode(dto);
		List<CrossSalePlan> planLists =queryKindList(returnMap,dto);
		response.setPlanLists(planLists);
	return response;
	}
	
	/**
	 * 根据费率因子组查询条款信息
	 * @param returnMap
	 * @param dto
	 * @return
	 */
	private List<CrossSalePlan> queryKindList(Map<String,Boolean> returnMap,QueryPlansRequestDTO dto){
		List<CrossSalePlan> planLists=Lists.newArrayList();
		for(String key:returnMap.keySet()){
			if(!returnMap.get(key)){
				continue;
			}
			List<Prpdration> rationList=prpdrationMapper.findByPlanSubcode(key);
			if(null==rationList||rationList.size()<1){
				continue;
			}
			CrossSalePlan plan=new CrossSalePlan();
			plan.setAgreementCode(dto.getAgreementCode());
			plan.setSeatCount(dto.getSeatCount());
			plan.setPlanCode(rationList.get(0).getPlancode());
			plan.setPlanIcpcode(key);
			plan.setPlanName(rationList.get(0).getPlancname());
			//plan.setPlanId(riskPlan.getPrpdRiskPlan().getSerialno());
			plan.setPlanEName(rationList.get(0).getPlanename());
			Double sumPremium   = rationList.stream()
					.mapToDouble(r -> r.getPremium().doubleValue()).sum();
			plan.setPlanPrice(String.valueOf(sumPremium));
			plan.setProCode(rationList.get(0).getRiskcode());
			BigDecimal sumAmount=new BigDecimal("0.00");//总保额
			String itemname =null;
			int carseat=dto.getSeatCount();
			List<CrossSaleKind> kinds=new ArrayList<CrossSaleKind>();
			for( Prpdration prpdRation: rationList  ){
				itemname =prpdRation.getItemcname();
				
				CrossSaleKind itemKind=new CrossSaleKind();
				itemKind.setCvgCode(prpdRation.getKindcode());
				BigDecimal amount=prpdRation.getAmount();
				itemKind.setAdultMax(amount.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
				//处理显示保额
				if(StringUtils.isNotBlank(itemname)&&itemname.indexOf("乘客")>-1){
					carseat=carseat-1;
					amount=amount.multiply(new BigDecimal(carseat));
					itemKind.setAdultMax(amount.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
					itemKind.setAdultStr(carseat+"*"+StringUtil.numberFormat(prpdRation.getAmount()));
				}
				if( "Y".equals(prpdRation.getCalculateflag())){
					sumAmount=sumAmount.add(new BigDecimal(itemKind.getAdultMax()));
				}
				
				//处理显示保额
				itemKind.setCvgName(prpdRation.getItemcname());
				itemKind.setCvgEName(prpdRation.getItemename());
				itemKind.setParaphrase(prpdRation.getKindcname());
				itemKind.setBenefitsCode(prpdRation.getItemcode());
				itemKind.setPremium(String.valueOf(prpdRation.getPremium()));
				itemKind.setQuantity(prpdRation.getUnitamount()==null||prpdRation.getUnitamount().intValue()==0?0:1);
				itemKind.setUnitamount(prpdRation.getUnitamount()==null||prpdRation.getUnitamount().doubleValue()==0? prpdRation.getAmount().doubleValue() : prpdRation.getUnitamount().doubleValue());
				kinds.add(itemKind);
			}
			
			plan.setSumAmount(sumAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
			plan.setKinds(kinds);
			planLists.add(plan);
		}
		return planLists;
	}
	/**
	 * 以Plancode和动态参数形式查询条款信息
	 * @param dto
	 * @return Map<String,Boolean>   key:plansubcode
	 */
	@Override
	public QueryPlansResponseDTO queryPlansByPlanCode(PlanDto planDto){
		QueryPlansResponseDTO response=new QueryPlansResponseDTO();
		String[] gpaPlanCode= {planDto.getGpaPlanCode()};
		Map<String,String> paraMap = new HashMap<String,String>();
		paraMap.put("00005", planDto.getCarType());
		paraMap.put("00006", planDto.getCarNature());
		paraMap.put("00007", planDto.getTonnage());
		paraMap.put("00001", planDto.getSeat());
		paraMap.put("00002", planDto.getDay());
		paraMap.put("00003", planDto.getAge());
		paraMap.put("00004", planDto.getRegion());
		
		QueryPlansRequestDTO dto=new QueryPlansRequestDTO();
		dto.setGpaPlanCode(gpaPlanCode);//计划Plancode
		dto.setParaMap(paraMap);//动态因子
		try{
			response.setFlowId(dto.getFlowId());
			response.setPdk(dto.getPdk());
			response.setStatus(false);
			if(null==dto||null==dto.getGpaPlanCode()||dto.getGpaPlanCode().length==0){
				response.setResultMessage("ERROR:计划代码gpaPlanCode不能为空");
				return response;
			}
			Map<String,Boolean> returnMap=new HashMap<String,Boolean>();
			StringBuilder paraSql = new StringBuilder();
			//筛选条件因子
			List<Map<String, Object>>	conditionList=null;
			paraSql = new StringBuilder("select plancode  as planCode,propscode   as propscode,propstype   as propstype,")
			.append(" propsvalue  as propsvalue, startvalue  as startvalue,endvalue    as endvalue from prpdplanprops b")
			.append(" where validstatus = '1' and plancode= ? ");
			for(String planCode:dto.getGpaPlanCode()){
				returnMap.put(planCode, true);
				conditionList = readJdbcTemplate.queryForList( paraSql.toString(),planCode);
				if(null==conditionList || conditionList.size()==0){
					continue;
				}
				//筛选条件因子
				selectByParam(returnMap,"planCode",paraMap,conditionList);
				
			}
			
			log.info("查询因子组sql:"+paraSql.toString());
			paraSql = new StringBuilder("select plansubcode as planSubcode,plancode    as planCode,propscode   as propscode,propstype   as propstype,")
			.append(" propsvalue  as propsvalue, startvalue  as startvalue,endvalue    as endvalue from prpdplansub b")
			.append(" where validstatus = '1' and plancode= ? ");
			@SuppressWarnings("unchecked")
			Map<String,Boolean> subMap=BeanUtilExt.copy(Map.class, returnMap);//因子组
			for(String key:subMap.keySet()){
				if(!subMap.get(key)){//plancode
					continue;
				}
				conditionList = readJdbcTemplate.queryForList( paraSql.toString(),key);
				 if(null!=conditionList && conditionList.size()>0){
					returnMap.put(key, false);//以组因子条件为准，条件因子作废
					 selectByParam(returnMap,"planSubcode",paraMap,conditionList);
				 }
			}
			 List<CrossSalePlan> planLists =queryKindList(returnMap,dto);
			response.setPlanLists(planLists);	
			response.setStatus(true);
//			redisUtils.set(planDto.toString(), response);
			redisUtils.set(Constants.SALE_QUERY_PLAN_SAVE + planDto.getAge() + ":" + planDto.getDay() + ":" + planDto.getGpaPlanCode()+":"+planDto.getSeat(), response);
//			Constants.SALE_QUERY_PLAN_SAVE + age + ":" + deadLine + ":" + planId, response
		}catch(Exception e) {
			response.setStatus(false);
		}
		return response;
	}
	/**
	 * 以代理人代码和动态参数形式查询 因子组
	 * @param dto
	 * @return Map<String,Boolean>   key:plansubcode
	 */
	private Map<String,Boolean> queryPlansubcode(QueryPlansRequestDTO dto){
		
		List<Map<String, Object>> planCodeList=null;
		
		StringBuilder prodSql = new StringBuilder();
		if(dto.getProducts().length==1){
			prodSql.append(" and riskcode='").append(dto.getProducts()[0]).append("' ");
		}else{
			prodSql.append(" and riskcode in(");
			for(int i=0;i<dto.getProducts().length;i++){
				prodSql.append("'").append(dto.getProducts()[i]).append("'");
				if(i!=dto.getProducts().length-1){
					prodSql.append(",");
				}else{
					prodSql.append(") ");
				}
			}
		}
		StringBuilder paraSql = new StringBuilder();
		
		paraSql.append("select plansubcode as plansubcode,plancode as planCode,propscode as propscode,propstype as propstype,propsvalue as propsvalue")
		.append(" ,startvalue as startvalue,endvalue  as endvalue ")
		.append(" from prpdplanprops b where validstatus='1' and  plancode in(")
	     .append(" select a.plancode from prpdriskplan a where a.validstatus='1'").append(prodSql)
	     .append(" and INSTR(applychannel,'")
	     .append(StringUtil.isEmpty(dto.getAgentCode())?"":dto.getAgentCode()).append("')>0 and (applycomcode='ALL' OR INSTR(applycomcode,'").append(dto.getCompanyCode())
	    .append("')>0) union all")
		.append(" select a.plancode from prpdriskplan a where a.validstatus='1'").append(prodSql)
		.append("  and applychannel is null and (applycomcode='ALL' OR INSTR(applycomcode,'").append(StringUtil.isEmpty(dto.getCompanyCode())?"":dto.getCompanyCode())
		.append("')>0) ) order by plancode");
		
		log.info("查询计划sql:"+paraSql.toString());
		 planCodeList = readJdbcTemplate.queryForList( paraSql.toString());
		 Map<String,Boolean> returnMap=new HashMap<String,Boolean>();
		 selectByParam(returnMap,"plansubcode",dto.getParaMap(),planCodeList);
		 return returnMap;
	}
	
	/**
	 * 根据条件筛选
	 * @param type
	 * @param paraMap
	 * @param planCodeList
	 * @return
	 */
	private Map<String,Boolean> selectByParam(Map<String,Boolean> returnMap,String type,Map<String,String> paraMap,
			List<Map<String,Object>> planCodeList){
		if(null==planCodeList || planCodeList.size()==0){
			return returnMap;
		}
		for(Map<String, Object> map:planCodeList){
			
			String plansubcode=(String)map.get(type);
			if(null==returnMap.get(plansubcode) ){
				returnMap.put(plansubcode, true);
			}
			if(!returnMap.get(plansubcode)){//已经不满足条件了
				continue;
			}
			String key=(String)map.get("propscode");
			String paraValue=paraMap.get(key);
			if(StringUtil.isEmpty(paraValue)){
				returnMap.put(plansubcode, false);//缺少因子,不满足条件
				continue;
			}
			String propstype=(String)map.get("propstype");
			String propsvalue=(String)map.get("propsvalue");
			String startvalue=(String)map.get("startvalue");
			String endvalue=(String)map.get("endvalue");
			if(("0".equals(propstype)&& paraValue.equals(propsvalue))
					|| ("1".equals(propstype)
						&&	new BigDecimal(paraValue).setScale(2, BigDecimal.ROUND_HALF_UP)
						.compareTo(new BigDecimal(startvalue).setScale(2, BigDecimal.ROUND_HALF_UP))>=0
						&&	new BigDecimal(paraValue).setScale(2, BigDecimal.ROUND_HALF_UP)
						.compareTo(new BigDecimal(endvalue).setScale(2, BigDecimal.ROUND_HALF_UP))<=0)){//符合条件
				returnMap.put(plansubcode, true);
			}else{
				returnMap.put(plansubcode, false);//不满足条件
			}
		}
		return returnMap;
	}
	
	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult addProduct(TbSpProduct tbSpProduct) {
		log.info(tbSpProduct.getStartDate().toString());
		log.info(tbSpProduct.getEndDate().toString());
		ServiceResult sr = new ServiceResult();
		TbSpFlow flow = flowDao.findByType(Constants.FLOW_PRODUCT);
		if (null == flow) {
			sr.setFail();
			sr.setResult("请先配置产品审批流！");
			return sr;
		}
		List<TbSpFlowDetail> details = flowDetailDao.findByFlowNo(flow.getFlowNo());
		if (CollectionUtils.isNotEmpty(details) && details.size() <= 1) {
			sr.setFail();
			sr.setResult("请先配置活动审批流！");
			return sr;
		}
		if (null == tbSpProduct.getProductConfigs() || tbSpProduct.getProductConfigs().size() == 0) {
			sr.setFail();
			sr.setResult("请求异常！");
			return sr;
		}
		String status = tbSpProduct.getStatus();
		String userId = Current.userInfo.get().getUserId();
		tbSpProduct.setQuantity(0);
		TbSpProduct newtp = new TbSpProduct();
		try {
			BeanUtilExt.copyProperties(newtp, tbSpProduct);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		// 积分入库初始数据
		List<TbSpProductConfig> tspcs = tbSpProduct.getProductConfigs();
		tbSpProduct.setStatus(Constants.APPROVE_ADD);
		TbSpProduct tp = productDao.save(tbSpProduct);

		for (TbSpProductConfig tcpc : tspcs) {
			tcpc.setProductId(tp.getId());
		}
		// 是否专属
		if (Constants.TRUE.equals(tbSpProduct.getIsExclusive())) {
			for (TbSpProductConfig tcpc : tspcs) {
				tcpc.setIsExclusive(Constants.TRUE);
				tcpc.setIsShow(Constants.FALSE);
			}
		} else {
			for (TbSpProductConfig tcpc : tspcs) {
				tcpc.setIsExclusive(Constants.FALSE);
				tcpc.setIsShow(Constants.TRUE);
			}
		}
		newtp.setProductConfigs(tspcs);
		log.info("-----status-----{}", status);
		newtp.setStatus(status);
		newtp.setId(tp.getId());
		String jsonstring = JSONObject.toJSONString(newtp, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);

		log.info("-----jsonstring-----{}", jsonstring);
		TbSpApprove tsa = new TbSpApprove();
		tsa.setStatus(Constants.FALSE);
		tsa.setApproveId(tp.getId().toString());
		tsa.setContent(jsonstring);
		tsa.setFlowNo(flow.getFlowNo());
		tsa.setFlowType(Constants.FLOW_PRODUCT);
		tsa.setFlowNode(flow.getLastFlowNode());
		tsa.setOriginalStatus(Constants.FALSE);// 新增产品初始状态为0
		tsa.setApplyTime(new Date());
		tsa.setApplyUser(userId);
		tsa.setType(Constants.PRODUCT_APPROVE);
		approveDao.save(tsa);
		productConfigDao.saveAll(tspcs);
		// 日志记录
		SysOperationLog operLog = new SysOperationLog();
		operLog.setIP(Current.IP.get());
		operLog.setLevel("1");
		operLog.setModule("产品管理");
		operLog.setOperationTime(new Date());
		operLog.setUserId(Current.userInfo.get().getUserId());
		operLog.setContent(userId + "申请添加产品-ID:" + tp.getId());
		operationLogDao.save(operLog);
		redisUtils.deletelike(Constants.RISK_CODE_NAME_INFO);
		sr.setResult(tp);
		return sr;

	}

	@Override
	public ServiceResult channelProductList(String userCode, Integer pageNumber, Integer pageSize) {
		ServiceResult sr = new ServiceResult();
		// if (StringUtils.isNotEmpty(userCode)) {
		// Integer num = (pageNumber - 1) * pageSize;
		// SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");// 设置日期格式
		// String today = df.format(new Date());
		// Integer i = productDao.findTotalProduct(today);
		// List<TbSpProduct> tbSpProductList =
		// productDao.findChannelProductList(userCode,num, pageSize);
		// Map<String, Object> map = new HashMap<String, Object>();
		// map.put("list", tbSpProductList);
		// Integer ia = exclusiveProductDao.countExclusive(userCode);
		// map.put("totalElements", i+ia);
		// sr.setResult(map);
		// }
		Sort sort = new Sort(Direction.ASC, "serialNo");
		Page<TbSpProduct> page = productDao.findAll(new Specification<TbSpProduct>() {
			public Predicate toPredicate(Root<TbSpProduct> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicate = new ArrayList<Predicate>();
				Predicate p1 = cb.equal(root.get("status").as(String.class), "3");
				Predicate p2 = cb.equal(root.get("status").as(String.class), "1");
				predicate.add(cb.or(p1, p2));
				predicate.add(cb.equal(root.get("isExclusive").as(String.class), "0"));
				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		}, PageRequest.of(pageNumber - 1, pageSize, sort));

		List<TbSpTopChannelAuthProduct> authProducts = topChannelAuthProductDao.findByUserCode(userCode);
		List<Integer> authProductId = Lists.newArrayList();
		for (TbSpTopChannelAuthProduct a : authProducts) {
			authProductId.add(a.getProductId());
		}

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("list", page.getContent());
		map.put("auth", authProducts);
		map.put("totalElements", page.getTotalElements());
		sr.setResult(map);
		// sr.setResult(page);
		return sr;
	}

	@Override
	public ServiceResult ProductList(String riskCode, String status, String branchCode, String productCname, String startDate, String endDate,
			Integer pageNumber, Integer pageSize) {
		log.info("startDate----" + startDate);
		log.info("endDate----" + endDate);
		ServiceResult sr = new ServiceResult();
		List<Order> orders = new ArrayList<Order>();
		orders.add(new Order(Direction.DESC, "status"));
		orders.add(new Order(Direction.ASC, "serialNo"));
		String userId = Current.userId.get();
		Integer roleId = roleUserDao.findByUserid(userId).getRoleid();
		Sort sort = new Sort(orders);
		Page<TbSpProduct> page = productDao.findAll(new Specification<TbSpProduct>() {
			public Predicate toPredicate(Root<TbSpProduct> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicate = new ArrayList<Predicate>();
				if (StringUtils.isNotEmpty(riskCode) && !"-1".equals(riskCode)) {
					log.info(riskCode);
					predicate.add(cb.equal(root.get("riskCode").as(String.class), riskCode));
				}
				if (StringUtils.isNotEmpty(productCname)) {
					log.info(productCname);
					predicate.add(cb.like(root.get("productCname").as(String.class), "%" + productCname + "%"));
				}
				if (StringUtils.isNotEmpty(startDate)) {
					log.info(startDate);
					predicate.add(cb.greaterThanOrEqualTo(root.get("startDate").as(String.class), startDate));
				}
				if (StringUtils.isNotEmpty(endDate)) {
					log.info(endDate);
					predicate.add(cb.lessThanOrEqualTo(root.get("endDate").as(String.class), endDate));
				}
				if (StringUtils.isNotEmpty(status) && !"-1".equals(status)) {
					log.info(status);
					if ("true".equals(status)) {
						Predicate p1 = cb.equal(root.get("status").as(String.class), "3");
						Predicate p2 = cb.equal(root.get("status").as(String.class), "1");
						predicate.add(cb.or(p1, p2));
					} else {
						predicate.add(cb.equal(root.get("status").as(String.class), status));
					}
				}

				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		}, PageRequest.of(pageNumber - 1, pageSize, sort));

		List<TbSpProduct> list = page.getContent();
		for (TbSpProduct p : list) {
			List<TbSpProductConfig> tspcs = productConfigDao.findByProductId(p.getId());
			if (null != tspcs && tspcs.size() != 0) {
				p.setProductConfigs(tspcs);
			}
			// TbSpApprove tsa =
			// approveDao.findByTypeAndApproveId(Constants.PRODUCT_APPROVE,
			// p.getId().toString(), Constants.APPROVE_WAIT);
			// if (null != tsa) {
			// p.setTbSpApprove(tsa);
			// }
			TbSpApprove tsa = approveDao.findApproveFlow(Constants.PRODUCT_APPROVE, p.getId().toString(), Constants.APPROVE_WAIT,
					Constants.FLOW_PRODUCT);
			if (null != tsa) {
				p.setTbSpApprove(tsa);
				TbSpFlowDetail flowDetail = flowDetailDao.findByNoAndNode(tsa.getFlowNo(), tsa.getFlowNode());
				if (null != flowDetail && StringUtils.isNotBlank(flowDetail.getUserCode())) {// 用户审批
					String[] users = flowDetail.getUserCode().split("&");
					boolean b = Arrays.asList(users).contains(userId);
					if (b) {
						p.setApproveAuth("true");
					} else {
						p.setApproveAuth("false");
					}
				}
				if (null != flowDetail && StringUtils.isNotBlank(flowDetail.getRoleCode())) {// 角色审批
					String[] roles = flowDetail.getRoleCode().split("&");
					boolean b = Arrays.asList(roles).contains(roleId.toString());
					if (b) {
						p.setApproveAuth("true");
					} else {
						p.setApproveAuth("false");
					}
				}
			}
		}
		sr.setResult(page);
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult updateProduct(TbSpProduct tbSpProduct) {

		ServiceResult sr = new ServiceResult();
		TbSpFlow flow = flowDao.findByType(Constants.FLOW_PRODUCT);
		if (null == flow) {
			sr.setFail();
			sr.setResult("请先配置产品审批流！");
			return sr;
		}
		List<TbSpFlowDetail> details = flowDetailDao.findByFlowNo(flow.getFlowNo());
		if (CollectionUtils.isNotEmpty(details) && details.size() <= 1) {
			sr.setFail();
			sr.setResult("请先配置产品审批流！");
			return sr;
		}
		log.info("getStatus===>:" + tbSpProduct.getStatus());
		String userId = Current.userInfo.get().getUserId();
		TbSpProduct dbProduct = productDao.findById(tbSpProduct.getId()).get();
		TbSpProduct newProduct = new TbSpProduct();
		List<TbSpProductConfig> newproductConfigs = tbSpProduct.getProductConfigs();
		try {
			BeanUtilExt.copyProperties(newProduct, dbProduct);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		if (!newProduct.differ(tbSpProduct) || !newproductConfigs.equals(productConfigDao.findByProductId(tbSpProduct.getId()))) {
			log.info("===============differ后不相同==================");
			try {
				TbSpProduct beanTbSpProduct = (TbSpProduct) BeanUtilExt.differAbeanToBbean(newProduct, tbSpProduct);
				// 是否专属
				if (Constants.TRUE.equals(tbSpProduct.getIsExclusive())) {
					for (TbSpProductConfig tcpc : newproductConfigs) {
						tcpc.setIsExclusive(Constants.TRUE);
					}
				} else {
					exclusiveProductDao.deleteByProductId(dbProduct.getId());
					productConfigDao.setExclusive(Constants.FALSE, dbProduct.getId());
				}
				beanTbSpProduct.setProductConfigs(newproductConfigs);
				String jsonstring = JSONObject.toJSONString(beanTbSpProduct, SerializerFeature.WriteMapNullValue,
						SerializerFeature.WriteNullStringAsEmpty);
				// 记录在审批表中
				TbSpApprove dbtsa = approveDao.findByTypeAndApproveId(Constants.PRODUCT_APPROVE, tbSpProduct.getId().toString(),
						Constants.APPROVE_WAIT);
				if (null != dbtsa) {
					dbtsa.setContent(jsonstring);
					approveDao.save(dbtsa);
				} else {
					TbSpApprove tsa = new TbSpApprove();
					tsa.setStatus(Constants.FALSE);
					tsa.setApproveId(tbSpProduct.getId().toString());
					tsa.setContent(jsonstring);
					tsa.setFlowNo(flow.getFlowNo());
					tsa.setFlowType(Constants.FLOW_PRODUCT);
					tsa.setFlowNode(flow.getLastFlowNode());
					tsa.setOriginalStatus(dbProduct.getStatus());
					tsa.setApplyTime(new Date());
					tsa.setApplyUser(Current.userInfo.get().getUserId());
					tsa.setType(Constants.PRODUCT_APPROVE);
					approveDao.save(tsa);
				}
				dbProduct.setModifyTime(tbSpProduct.getModifyTime());
				dbProduct.setModifyUser(Current.userInfo.get().getUserId());
				if (Constants.TRUE.equals(dbProduct.getStatus())) {
					dbProduct.setStatus(Constants.APPROVE_UP_UPDATE);
				} else {
					dbProduct.setStatus(Constants.APPROVE_DOWN_UPDATE);
				}
				productDao.save(dbProduct);
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}

		} else {
			log.info("===============differ后相同==================");
			productDao.save(tbSpProduct);
			// 专属
			if (Constants.TRUE.equals(tbSpProduct.getIsExclusive())) {
				for (TbSpProductConfig tcpc : newproductConfigs) {
					tcpc.setIsExclusive(Constants.TRUE);
				}
				productConfigDao.saveAll(newproductConfigs);
			} else {
				exclusiveProductDao.deleteByProductId(dbProduct.getId());
				productConfigDao.setExclusive(Constants.FALSE, dbProduct.getId());
			}
		}

		SysOperationLog operLog = new SysOperationLog();
		operLog.setIP(Current.IP.get());
		operLog.setLevel("1");
		operLog.setModule("产品管理");
		operLog.setOperationTime(new Date());
		operLog.setUserId(userId);
		operLog.setContent(userId + "申请修改产品信息-ID:" + tbSpProduct.getId());
		operationLogDao.save(operLog);
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult removeProduct(String[] list) {
		ServiceResult sr = new ServiceResult();
		String userId = Current.userInfo.get().getUserId();
		for (int i = 0; i < list.length; i++) {
			productDao.updateStatus("0", Integer.parseInt(list[i]));
			SysOperationLog operLog = new SysOperationLog();
			operLog.setIP(Current.IP.get());
			operLog.setLevel("3");
			operLog.setModule("产品管理");
			operLog.setOperationTime(new Date());
			operLog.setUserId(Current.userInfo.get().getUserId());
			operLog.setContent(userId + "删除产品-ID:" + Integer.parseInt(list[i]));
			operationLogDao.save(operLog);
			TbSpHotproduct thp = hotProductDao.findByProductId(Integer.parseInt(list[i]));
			if (null != thp && null != thp.getId()) {
				thp.setStatus(Constants.FALSE);
				hotProductDao.save(thp);
			}
		}
		redisUtils.deletelike(Constants.RISK_CODE_NAME_INFO);
		sr.setSuccess();
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult rebackProduct(String[] list) {
		ServiceResult sr = new ServiceResult();
		String userId = Current.userInfo.get().getUserId();
		for (int i = 0; i < list.length; i++) {
			productDao.updateStatus(Constants.TRUE, Integer.parseInt(list[i]));
			SysOperationLog operLog = new SysOperationLog();
			operLog.setIP(Current.IP.get());
			operLog.setLevel("1");
			operLog.setModule("产品管理");
			operLog.setOperationTime(new Date());
			operLog.setUserId(Current.userInfo.get().getUserId());
			operLog.setContent(userId + "恢复产品-ID:" + Integer.parseInt(list[i]));
			operationLogDao.save(operLog);
		}
		redisUtils.deletelike(Constants.RISK_CODE_NAME_INFO);
		sr.setSuccess();
		return sr;
	}

	@Override
	public List<String> riskCodeDistinct() {

		List<String> code_name = (List<String>) redisUtils.get(Constants.RISK_CODE_NAME_INFO);
		if (null != code_name && code_name.size() != 0) {
			return code_name;
		} else {
			List<String> dbcode_name = productDao.riskCodeDistinct();
			redisUtils.set(Constants.RISK_CODE_NAME_INFO, dbcode_name);
			return dbcode_name;
		}
	}

	@Override
	public ServiceResult setHot(TbSpHotproduct tbSpHotproduct) {

		ServiceResult sr = new ServiceResult();
		TbSpHotproduct dbthp = hotProductDao.findByProductIdAndBranchCode(tbSpHotproduct.getProductId(), tbSpHotproduct.getBranchCode());
		if (null != dbthp && null != dbthp.getId()) {
			tbSpHotproduct.setStatus(Constants.TRUE);
			tbSpHotproduct.setId(dbthp.getId());
			sr.setResult(hotProductDao.save(tbSpHotproduct));
		} else {
			tbSpHotproduct.setStatus(Constants.TRUE);
			sr.setResult(hotProductDao.save(tbSpHotproduct));
		}
		return sr;
	}

	// 查询佣金
	@Override
	public PropsalSaveRequestDto findRate(PropsalSaveRequestDto requestDto, boolean isAxtx) {
		StringBuilder logMsg = new StringBuilder();
		InsureQuery insureQuery = requestDto.getInsureQuery();
		// 查询佣金
		String refereeId = insureQuery.getRefereeId();
		String userCode = requestDto.getUser().getUserCode();
		boolean isSetRate = false;
		Double rate = 0.0;
		TbSysHotarea hotArea = null;
		String user = "";
		BigDecimal rateBase = new BigDecimal(100);
		Integer proIdIn = Integer.parseInt(insureQuery.getProductId());
		String proId = insureQuery.getProductId();

		// 设置热门地区业务关系代码
		if (insureQuery.getIsHotArea() && isAxtx) {
			hotArea = tbSysHotareaDao.findByAreaCode(insureQuery.getAreaCode());
			insureQuery.setChannelName(hotArea.getBranchName());
			requestDto.getAxtx().setAgreementCode(hotArea.getAgreementNo());
			requestDto.getAxtx().setSalerName(hotArea.getSaleName());
			requestDto.getAxtx().setSaleCode(hotArea.getSaleCode());
			logMsg.append("-设置地区业务关系代码:" + hotArea.getAgreementNo());
		} else if (insureQuery.getIsHotArea()) {
			hotArea = tbSysHotareaDao.findByAreaCode(insureQuery.getAreaCode());
			insureQuery.setChannelName(hotArea.getBranchName());
			requestDto.getProposalSaveReq().getPolicyDataDto().getAgentDto().setAgreementCode(hotArea.getAgreementNo());
			requestDto.getProposalSaveReq().getPolicyDataDto().getAgentDto().setSalerName(hotArea.getSaleName());
			requestDto.getProposalSaveReq().getPolicyDataDto().getAgentDto().setSalerNumber(hotArea.getSaleCode());
			// log = " 设置地区业务关系代码:"
			logMsg.append("-设置地区业务关系代码:" + hotArea.getAgreementNo());
		}

		if (!"LCB".equals(insureQuery.getShareUid()) && !"lcb".equals(insureQuery.getShareUid())) {

			// 存在推荐人
			if (StringUtil.isNotEmpty(refereeId)) {
				user = refereeId;
			} else if (StringUtil.isNotEmpty(userCode)) {
				// 不存在推荐人
				user = userCode;
			}
			user = userService.getTopUserCode(user);
			TbSpUser userBra = userDao.findByUserCode(user);
			if (userBra == null) {
				requestDto.setLog("-没有查询到用户:" + userCode);
				return requestDto;
			}
			if (Constants.USER_REGISTER_TYPE_1.equals(userBra.getRegisterType())
					|| Constants.USER_REGISTER_TYPE_2.equals(userBra.getRegisterType())) {
				logMsg.append("-渠道用户");
				List<String> userTopList = insureService.topUser(user, new ArrayList<String>());
				if (CollectionUtils.isNotEmpty(userTopList) && userTopList.size() > 1) {
					user = userTopList.get(userTopList.size() - 1);
					userBra = userDao.findByUserCode(user);
					logMsg.append("-查找顶级渠道为:" + user);
					if (StringUtils.isNotBlank(userBra.getAgrementNo())) {
						logMsg.append("-顶级渠道存在业务关系代码:" + userBra.getAgrementNo());
						if (isAxtx) {
							requestDto.getAxtx().setAgreementCode(userBra.getAgrementNo());
							requestDto.getAxtx().setSalerName(userBra.getSaleName());
							requestDto.getAxtx().setSaleCode(userBra.getSaleCode());
						} else {
							requestDto.getProposalSaveReq().getPolicyDataDto().getAgentDto().setAgreementCode(userBra.getAgrementNo());
							requestDto.getProposalSaveReq().getPolicyDataDto().getAgentDto().setSalerName(userBra.getSaleName());
							requestDto.getProposalSaveReq().getPolicyDataDto().getAgentDto().setSalerNumber(userBra.getSaleCode());
						}
					}
				}
			}
			logMsg.append("-是否店主" + userBra.getStoreFlag());

			if (!Constants.USER_STORE_FLAG_1.equals(userBra.getStoreFlag())) {
				requestDto.setLog(logMsg.toString());
				return requestDto;
			}
			logMsg.append("-用户类型" + userBra.getUserType());
			if (!Constants.USER_TYPE_3.equals(userBra.getUserType())) {
				requestDto.setLog(logMsg.toString());
				return requestDto;
			}

			if (!Strings.isNullOrEmpty(user)) {
				Double reRate = shopService.getRate(rate, user, proId, true);
				if (reRate != 0.0) {
					rate = reRate;
					isSetRate = true;
				}
			}
			// 都没有查询到专属佣金 取当前所属地区
			if (!isSetRate && StringUtils.isNotBlank(user)) {
				String areaCode = "";
				if (StringUtils.isNotBlank(userBra.getUserCode()) && StringUtils.isNotBlank(userBra.getBranchCode())) {
					areaCode = userBra.getBranchCode();
					logMsg.append("   用户bra" + areaCode);
				} else {
					if (StringUtils.isNotBlank(userBra.getAreaCode())) {
						areaCode = userBra.getAreaCode();
						logMsg.append("   用户are" + areaCode);
					} else {
						logMsg.append("   地区are" + areaCode);
						areaCode = insureQuery.getBranchCode();
					}

				}
//				TbSysHotarea tbHotArea = tbSysHotareaDao.findByAreaCode(areaCode);
//				TbSpProductConfig prConfig = productConfigDao.findRateBybranch(proIdIn, tbHotArea.getBranchCode());
				TbSpProductConfig prConfig = productConfigDao.findRateBybranch(proIdIn, areaCode);
				if (prConfig != null) {
					BigDecimal curRate = new BigDecimal(prConfig.getRate());
					rate = curRate.multiply(rateBase).doubleValue();
					logMsg.append("   地区Rate:");
					isSetRate = true;
				}
			}
			if (isSetRate) {
				BigDecimal bean = new BigDecimal(rate);// 宝豆
				bean = bean.setScale(2, BigDecimal.ROUND_HALF_UP);
				rate = bean.doubleValue();
				logMsg.append("-比例" + rate.toString());
			}
			if (!isAxtx && isSetRate) {
				List<InsuredBaseDto> insuredItemProcutDtoList = requestDto.getProposalSaveReq().getPolicyDataDto().getInsuredItemProcutDtoList();
				for (int i = 0; i < insuredItemProcutDtoList.size(); i++) {
					insuredItemProcutDtoList.get(i).getProductDto().setComm1Rate(rate.toString());
				}
				requestDto.getProposalSaveReq().getPolicyDataDto().setInsuredItemProcutDtoList(insuredItemProcutDtoList);
			} else if (isAxtx && isSetRate) {
				requestDto.setComm1Rate(rate.toString());
			}

			requestDto.setLog(logMsg.toString());
		}

		return requestDto;
	}

	@Transactional(propagation = Propagation.REQUIRES_NEW) // 事务
	@Override
	public ServiceResult savePlan(PropsalSaveRequestDto requestDto) {
		InsureQuery insureQuery = requestDto.getInsureQuery();
		// TbSpUser user = new TbSpUser();
		// user.setUserCode(Current.userCode.get());
		// requestDto.setUser(user);
		Map map = (Map) redisUtils.get(Constants.SYS_SERVICE_INFO);
		SysServiceInfo callServiceInfo = (SysServiceInfo) map.get(CoreServiceEnum.CALLBACK_URL.getUrlKey());
		// requestDto.getProposalSaveReq().getPolicyDataDto().getMainHeadDto().setCallBackUrl("https://uat-lm.libertymutual.com.cn/sale/admin-cxb/callback");
		requestDto.getProposalSaveReq().getPolicyDataDto().getMainHeadDto().setCallBackUrl(callServiceInfo.getUrl());
		requestDto = findRate(requestDto, false);
		TbSpSaleLog saleLog = new TbSpSaleLog();

		requestDto.getProposalSaveReq().getPolicyDataDto().getMainHeadDto().setTrdSalesCode(insureQuery.getSingleMember());
		TbSpOrder order = new TbSpOrder();
		saleLog.setOperation(TbSpSaleLog.OPERATION_INSURE);
		saleLog.setRequestTime(new Date());
		ServiceResult sr = new ServiceResult();
		// requestDto.getProposalSaveReq().getPolicyDataDto().getMainHeadDto()
		ProposalSaveForRequestDto request = requestDto.getProposalSaveReq();
		List<InsuredBaseDto> insuredItemProcutDtoList = request.getPolicyDataDto().getInsuredItemProcutDtoList();
		AddressBaseDto addressDto = request.getPolicyDataDto().getAddressDto();
		AppliBaseDto appliDto = request.getPolicyDataDto().getAppliDto();
		PeriodBaseDto periodDto = request.getPolicyDataDto().getPeriodDto();
		AgentBaseDto agentDto = request.getPolicyDataDto().getAgentDto();
		long beginTime;
		long endTime;
		long curDate = new Date().getTime();
		String planId = insureQuery.getPlanId();
		String deadLine = insureQuery.getDeadLine();
		TbSpProduct pro = productDao.findByShowId(Integer.parseInt(insureQuery.getProductId()));
		if (null == pro) {
			sr.setFail();
			sr.setResult("该产品已经下架，请选择其他产品进行投保");
			return sr;
		}

		if (StringUtils.isBlank(addressDto.getAddressName())) {
			request.getPolicyDataDto().getAddressDto().setAddressName("不适用");
		}
		if (StringUtils.isBlank(addressDto.getBuildStructure())) {
			request.getPolicyDataDto().getAddressDto().setBuildStructure("0005");
		}
		if (StringUtils.isNotBlank(request.getPolicyDataDto().getMainHeadDto().getLicenseno())) {
			request.getPolicyDataDto().getMainHeadDto().setLicenseno("车牌号:" + request.getPolicyDataDto().getMainHeadDto().getLicenseno());
		}
		if (StringUtils.isNotBlank(request.getPolicyDataDto().getMainHeadDto().getVinno())) {
			request.getPolicyDataDto().getMainHeadDto().setVinno("车架号:" + request.getPolicyDataDto().getMainHeadDto().getVinno());
		}

		// othEngage
		// request.getPolicyDataDto().getMainHeadDto().setOthEngage(insureQuery.getOtherInfo());
		request.getPolicyDataDto().getAppliDto().setPayMth("7");
		try {
			beginTime = DateUtil.convertStringToDateYMDhm(periodDto.getStartDate() + " " + periodDto.getStartHour() + ":00").getTime();
			endTime = DateUtil.convertStringToDateYMDhm(periodDto.getEndDate() + " " + periodDto.getEndHour() + ":00").getTime();
		} catch (Exception e) {
			sr.setFail();
			sr.setResult("投保失败,01，请稍后再试！");
			log.error(TbSpOrder.ERROR_01);
			saleLog.setMark(TbSpOrder.ERROR_01);
			saleLog.setRequestData(BeanUtilExt.toJsonString(requestDto));
			spSaleLogDao.save(saleLog);
			return sr;
		}
		// 日期信息不符合投保规则
		if (beginTime < curDate || endTime < beginTime || curDate > endTime) {
			sr.setFail();
			log.error(TbSpOrder.ERROR_01);
			saleLog.setMark(TbSpOrder.ERROR_01);
			saleLog.setRequestData(BeanUtilExt.toJsonString(requestDto));
			spSaleLogDao.save(saleLog);
			sr.setResult("投保失败,01,请稍后再试！");
			return sr;
		}
		// 01:投保失败,日期错误
		Float sumCount = 0F;
		try {
			// 重新计算价格
			for (int i = 0; i < insuredItemProcutDtoList.size(); i++) {
				List<ItemKindBaseDto> itemKindDtoList = new ArrayList<ItemKindBaseDto>();

				int age = DateUtil.getAgeByBrithday(DateUtil.convertStringToDate(insuredItemProcutDtoList.get(i).getInsuredDto().getBirth()));
				// System.out.println("-------------------------------planId----------------------------------");
				// System.out.println(redisUtils.get(Constants.SALE_QUERY_PLAN_PRICE+age+deadLine+planId));
				// System.out.println(redisUtils.get(Constants.SALE_QUERY_PLAN_SAVE+age+":"+deadLine+":"+planId));
				// QueryPlansResponseDTO
				Object objData = new QueryPlansResponseDTO();
				objData = redisUtils.get(Constants.SALE_QUERY_PLAN_SAVE + age + ":" + deadLine + ":" + planId);
				if (null == objData) {
					queryPlan(planId, age, Integer.parseInt(deadLine));
					objData = (QueryPlansResponseDTO) redisUtils.get(Constants.SALE_QUERY_PLAN_SAVE + age + ":" + deadLine + ":" + planId);
				}
				QueryPlansResponseDTO savePlans = (QueryPlansResponseDTO) objData;

				List<CrossSaleKind> kinds = savePlans.getPlanLists().get(0).getKinds();
				Float price = Float.parseFloat(savePlans.getPlanLists().get(0).getPlanPrice());
				DecimalFormat decimalFormat = new DecimalFormat(".00");
				Float sum = 0F;
				for (int j = 0; j < kinds.size(); j++) {
					Float premium = Float.parseFloat(kinds.get(j).getPercentage()) / 100;
					Float itemPrice = Float.parseFloat(decimalFormat.format(premium * price));
					ItemKindBaseDto ikDto = new ItemKindBaseDto();
					if (j != kinds.size() - 1) {
						sum += itemPrice;
						ikDto.setPremium(itemPrice.toString());
					} else {
						Float pri = price - sum;
						ikDto.setPremium(pri.toString());
					}
					ikDto.setKindCode(kinds.get(j).getBenefitsCode());
					ikDto.setItemCode(kinds.get(j).getCvgCode());
					ikDto.setAmount(kinds.get(j).getAdultMax());
					ikDto.setItemName(kinds.get(j).getCvgName() + " " + kinds.get(j).getCvgEName());
					ikDto.setAttribute4(kinds.get(j).getAdultStr());
					itemKindDtoList.add(ikDto);
				}
				sumCount += price;
				insuredItemProcutDtoList.get(i).setItemKindDtoList(itemKindDtoList);
			}

		} catch (Exception e) {
			saleLog.setMark(TbSpOrder.ERROR_02);
			saleLog.setRequestData(BeanUtilExt.toJsonString(requestDto));
			spSaleLogDao.save(saleLog);
			sr.setFail();
			// 02:重新计算价格错误
			log.error(TbSpOrder.ERROR_02);
			sr.setResult("投保失败,02,请稍后再试！");
			return sr;
		}

		request.getPolicyDataDto().setInsuredItemProcutDtoList(insuredItemProcutDtoList);
		TbSpUser user = requestDto.getUser();
		if (null == request || null == request.getPolicyDataDto()) {
			sr.setResult("请求参数不能为空！");
			return sr;
		}

		// -----------------------业务关系代码 产销人员-----------------------------
		try {
			String userCode = "";
			if (StringUtils.isNotBlank(insureQuery.getRefereeId())) {
				userCode = insureQuery.getRefereeId();
			} else if (StringUtils.isNotBlank(user.getUserCode())) {
				userCode = user.getUserCode();
			}
			order = insureService.setAgrInfo(order, agentDto.getAgreementCode(), userCode);
			// -------------------查询产销人员--------------------------
			if (StringUtils.isNotBlank(agentDto.getSalerNumber()) && StringUtils.isBlank(agentDto.getSalerName())) {
				request.getPolicyDataDto().getAgentDto()
						.setSalerName(insureService.getSaleCode(agentDto.getAgreementCode(), agentDto.getSalerNumber()));
			}

		} catch (Exception e) {
			saleLog.setMark("查询业务关系代码对应信息出错");
			spSaleLogDao.save(saleLog);
			log.error(e.toString());
		}

		SysServiceInfo sysServiceInfo = (SysServiceInfo) map.get(CoreServiceEnum.COMMON_REQUEST.getUrlKey());
		request.setConsumerId(consumerId);
		request.setOperateCode(operateCode);
		request.setUsercode(userCode);
		request.setPassword(passWord);
		request.setIsAutoUndwrt("1");
		CommonRequestDto commonRequestDto = new CommonRequestDto();
		commonRequestDto.setPartnerAccountCode(sysServiceInfo.getUserName());
		String flowId = iSequenceService.getOrderSequence(insureQuery.getRisk());
		// commonRequestDto.setFlowId(commonRequestDto.getPartnerAccountCode() +
		// flowId);
		request.setSequenceId(flowId);
		// String BussFormNo =
		// request.getPolicyDataDto().getMainHeadDto().getBussFromNo();
		// if (StringUtils.isEmpty(BussFormNo)) {
		// BussFromNo = commonRequestDto.getPartnerAccountCode() +new
		// Date().getTime()+new Random().nextInt(10);
		// String BussFormNo = new Date().getTime()+UUID.getShortUuid();
		String BussFormNo = insureQuery.getRisk() + DateUtil.getStringDateYyMMdd() + UUID.getShortUuid();
		request.getPolicyDataDto().getMainHeadDto().setBussFromNo(BussFormNo);
		// }
		commonRequestDto.setFlowId(BussFormNo);
		commonRequestDto.setRequestJson(JSON.toJSONString(request));
		commonRequestDto.setRequestType(insureQuery.getRisk() + "_SAVE");
		saleLog.setRequestData(commonRequestDto.toString() + "   URL:" + insureQuery.getAccessUrl() + "<br>LOG:" + requestDto.getLog());
		saleLog.setUserCode(user.getUserCode());
		/*
		 * HttpHeaders headers = new HttpHeaders(); headers.add("account-code",
		 * sysServiceInfo.getUserName()); headers.add("request-time", String.valueOf(new
		 * Date().getTime())); headers.add("soa-token",
		 * pwdEncoder.encodePassword(sysServiceInfo.getPassword(), String.valueOf(new
		 * Date().getTime())));
		 */

		log.info("***************commonRequestDto.toString()***************");
		log.info(commonRequestDto.toString());

		HttpEntity<CommonRequestDto> requestEntity = new HttpEntity<CommonRequestDto>(commonRequestDto,
				RequestUtils.genEncryptHttpHeaders(sysServiceInfo.getUserName(), sysServiceInfo.getPassword()));
		try {
			sr = restTemplate.postForObject(sysServiceInfo.getUrl(), requestEntity, ServiceResult.class);
			if (sr != null)
				saleLog.setResponseData(sr.toString());
		} catch (Exception e) {
			saleLog.setMark(TbSpOrder.ERROR_03);
			spSaleLogDao.save(saleLog);
			sr.setFail();
			sr.setResult("投保失败,03,请稍后再试！");
			log.error(TbSpOrder.ERROR_03);
			// 03:请求超时
			return sr;
		}
		// if(sr.getState() == ServiceResult.STATE_SUCCESS) {

		// 记录订单

		log.info("***************sr.getResult().toString()***************{}", sr.getResult());

		LinkedHashMap<String, String> saveMap = new LinkedHashMap<String, String>();
		try {
			saveMap = (LinkedHashMap<String, String>) sr.getResult();
		} catch (Exception e) {
			saleLog.setMark(TbSpOrder.ERROR_04);
			spSaleLogDao.save(saleLog);
			sr.setResult("投保失败,04,请稍后再试！");
			log.error(TbSpOrder.ERROR_04);
			// 03:返回信息不存在或错误
			sr.setFail();
			return sr;
		}

		// JSONObject
		// jsonObjectSr=JSONObject.parseObject(sr.getResult().toString());
		// ResponseBaseDto saveSerRes =
		// jsonObjectSr.toJavaObject(ResponseBaseDto.class);
		if (StringUtils.isBlank(saveMap.get("responseJson"))) {
			sr.setResult("投保失败,05,请稍后再试！");
			saleLog.setMark(TbSpOrder.ERROR_05);
			spSaleLogDao.save(saleLog);
			log.error(TbSpOrder.ERROR_05);
			// 05:返回信息不存在responseJson
			sr.setFail();
			return sr;
		}
		JSONObject jsonObjectRID = JSONObject.parseObject(saveMap.get("responseJson"));
		ResponseInsureDto riDto = jsonObjectRID.toJavaObject(ResponseInsureDto.class);
		String rate = "";
		if ("true".equals(riDto.getSuccess())) {
			order.setOrderNo(flowId); // 订单号
			if (user.getUserCode() != null) {
				order.setUserId(userService.getTopUserCode(user.getUserCode())); // 用户id
			} else {
				order.setUserId(""); // 用户id
			}
			// 回写投保人和被保险人信息
			try {
				// 投保人基本信息回写
				TbSpApplicant appliSpal = new TbSpApplicant();
				appliSpal.setOrderNo(flowId); // 订单号
				// appliDto
				appliSpal.setNatureType(appliDto.getInsuredType()); // 性质
				appliSpal.setType(TbSpApplicant.TYPE_POLICY); // 类别:1投保人,2被保人,3受益人
				appliSpal.setName(appliDto.getInsuredName()); // 姓名
				appliSpal.setCarType(appliDto.getIdentifyType()); // 证件类型
				appliSpal.setCarId(appliDto.getIdentifyNumber()); // 证件号码
				appliSpal.setMobile(appliDto.getLinkMobile()); // 手机
				appliSpal.setEmail(appliDto.getEmail()); // 邮箱
				appliSpal.setOccupation(""); // 职业类别
				appliSpal.setRelation(""); // 与投保人关系
				appliSpal.setRemark(""); // 备注
				appliSpal.setBirth(DateUtil.convertStringToDate(appliDto.getBirth()));
				appliSpal.setSex(appliDto.getSex());
				applicantDao.save(appliSpal);

				for (int i = 0; i < insuredItemProcutDtoList.size(); i++) {
					InsuredDto insuredDto = insuredItemProcutDtoList.get(i).getInsuredDto();
					TbSpApplicant insuredSpal = new TbSpApplicant();
					insuredSpal.setOrderNo(flowId);
					if (StringUtils.isNotBlank(insuredItemProcutDtoList.get(i).getProductDto().getComm1Rate())) {
						rate = insuredItemProcutDtoList.get(i).getProductDto().getComm1Rate();
						log.info("Comm1Rate={}", rate);
					} else {
						rate = "";
					}

					insuredSpal.setType(TbSpApplicant.TYPE_INSURED);
					insuredSpal.setName(insuredDto.getInsuredName());
					insuredSpal.setCarType(insuredDto.getIdentifyType());
					insuredSpal.setCarId(insuredDto.getIdentifyNumber());
					insuredSpal.setMobile(insuredDto.getLinkMobile());
					insuredSpal.setEmail(insuredDto.getEmail());
					insuredSpal.setOccupation(insuredDto.getOccupationName());
					insuredSpal.setRelation(insuredDto.getIdentifyType());
					insuredSpal.setNatureType("1");
					insuredSpal.setRemark("");
					insuredSpal.setBirth(DateUtil.convertStringToDate(insuredDto.getBirth()));
					insuredSpal.setSex(insuredDto.getSex());
					applicantDao.save(insuredSpal);
				}
			} catch (Exception e) {
				sr.setFail();
				saleLog.setMark(TbSpOrder.ERROR_06);
				spSaleLogDao.save(saleLog);
				log.error(TbSpOrder.ERROR_06);
				sr.setResult("投保失败,06,请稍后再试！");
				// 06:信息表回写失败

				log.error(e.toString());
				// TODO Auto-generated catch block
				// e.printStackTrace();
				return sr;
			}

			// 回写订单表
			try {
				// order.setAccessUrl(requestDto.getAccessUrl());
				order = insureService.setOrderInitData(order, insureQuery);

				order.setAmount(Double.parseDouble(sumCount.toString())); // 总金额

				if (StringUtils.isNotBlank(rate)) {
					// 精度问题，必须要设置固定位数 bob.kuang 20180211
					BigDecimal rateDec = new BigDecimal(rate);
					rate = rateDec.setScale(6, RoundingMode.HALF_DOWN).toPlainString();
				}
				order.setCommissionRate(rate);
				// order.setRiskCode(requestDto.getRisk()); // 险种CODE
				order.setIdNo(appliDto.getIdentifyNumber()); // 证件号码
				order.setPlanCode(insuredItemProcutDtoList.get(0).getProductDto().getProductCode()); // 获得计划代码
				order.setStartDate(DateUtil.convertStringToDate(periodDto.getStartDate())); // 起保日期
				order.setEndDate(DateUtil.convertStringToDate(periodDto.getEndDate())); // 保险止限额
				order.setOrderDetail(JSON.toJSONString(requestDto.getKinds())); // 订单详情

				order.setHouseAddress(addressDto.getRegion()); // 房屋地址
				// order.setPayWay(appliDto.getPayMth()); // 支付方式
				order.setProposalNo(riDto.getBussNewNo());
				order.setAdditionalInfo(insureQuery.getOtherInfo());
				order.setRefereeId(userService.getTopUserCode(insureQuery.getRefereeId())); // 推荐人

				order = insureService.setInsureBrachCode(order, insureQuery, requestDto);

				order.setTravelDestination(requestDto.getProposalSaveReq().getPolicyDataDto().getMainHeadDto().getArrivalCountryName());
				order.setAgreementNo(agentDto.getAgreementCode()); // 业务关系代码
				order.setApplicantName(appliDto.getInsuredName()); // 投保人名字
				order.setSaleType(""); // 销售渠道
				order.setPlanId(insureQuery.getPlanId());
				order.setFrameNum(requestDto.getProposalSaveReq().getPolicyDataDto().getMainHeadDto().getVinno());
				order.setPlateNum(requestDto.getProposalSaveReq().getPolicyDataDto().getMainHeadDto().getLicenseno());
				order.setAddress(addressDto.getAddressName());
				// order.setBranchOffice(requestDto.getChannelName());
				spOrderDao.save(order);
			} catch (Exception e) {
				sr.setFail();
				sr.setResult("投保失败,07,请稍后再试！");
				saleLog.setMark(TbSpOrder.ERROR_07);
				spSaleLogDao.save(saleLog);
				log.error(TbSpOrder.ERROR_07);
				// 07:订单表回写失败
				log.error(e.getMessage());
				// TODO Auto-generated catch block
				// e.printStackTrace();
				// return sr;
			}
		}
		spSaleLogDao.save(saleLog);
		return sr;
	}

	@Override
	public ServiceResult getHotProduct(Integer productId, String branchCode) {
		ServiceResult sr = new ServiceResult();
		sr.setResult(hotProductDao.findByProductIdAndBranchCode(productId, branchCode));
		return sr;
	}

	@Override
	public ServiceResult hotProductList(String branchCode, Integer pageNumber, Integer pageSize) {
		ServiceResult sr = new ServiceResult();
		Sort sort = new Sort(Direction.ASC, "serialNo");
		if (StringUtils.isNotEmpty(branchCode)) {
			Pageable pageable = PageRequest.of(pageNumber - 1, pageSize, sort);
			sr.setResult(productDao.findList(branchCode, pageable));
		} else {
			Pageable pageable = PageRequest.of(pageNumber - 1, pageSize, sort);
			sr.setResult(productDao.findAllList(pageable));
		}

		return sr;
	}

	@Override
	public ServiceResult branchHotProductList(String branchCode, Integer pageNumber, Integer pageSize) {

		ServiceResult sr = new ServiceResult();
		log.info("branchCode------>:" + branchCode);
		Integer num = (pageNumber - 1) * pageSize;
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");// 设置日期格式
		String today = df.format(new Date());
		try {
			List<TbSpProduct> tbSpProductList = productDao.findBranchHotProductList(today, branchCode, num, pageSize);
			List<TbSpHotproduct> hotlist = hotProductDao.findByBranchCodeAndStatus(branchCode);
			TbSpProduct tbSpProduct = null;
			for (int i = 0; i < tbSpProductList.size(); i++) {
				tbSpProduct = tbSpProductList.get(i);
				for (int j = 0; j < hotlist.size(); j++) {
					/// if (List.get(i).getId().equals(hotlist.get(j).getProductId()) ||
					/// List.get(i).getId() == hotlist.get(j).getProductId() ) {
					if (tbSpProduct.getId().intValue() == hotlist.get(j).getProductId().intValue()
							|| tbSpProduct.getId().compareTo(hotlist.get(j).getProductId()) == 0) {
						tbSpProduct.hotFlag = true;
						break;
					} else {
						tbSpProduct.hotFlag = false;
					}
				}
				log.info("hotflag-----:{}", tbSpProduct.hotFlag);
				log.info("id-----:{}", tbSpProduct.getId());
			}
			Integer i = productDao.findTotalProduct(today);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("list", tbSpProductList);
			map.put("total", i);
			sr.setResult(map);
		} catch (Exception e) {
			log.info("数据异常！");
			sr.setFail();
		}
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult removeHotProduct(String branchCode, String[] list) {
		ServiceResult sr = new ServiceResult();
		Map<String, Map<String, SysCodeNode>> codeMap = (Map<String, Map<String, SysCodeNode>>) redisUtils.get(Constants.MAP_CODE);
		SysCodeNode branch = codeMap.get("BranchCode").get(branchCode);
		for (int i = 0; i < list.length; i++) {
			hotProductDao.updateStatus(branchCode, Integer.parseInt(list[i]));
			SysOperationLog operLog = new SysOperationLog();
			operLog.setIP(Current.IP.get());
			operLog.setLevel("3");
			operLog.setModule("热销产品管理");
			operLog.setOperationTime(new Date());
			operLog.setUserId(Current.userInfo.get().getUserId());
			operLog.setContent("删除了" + branch.getCodeCname() + "的热销产品-PRODUCT_ID:" + Integer.parseInt(list[i]));
			operationLogDao.save(operLog);
		}
		sr.setSuccess();
		return sr;
	}

	@Override
	public ServiceResult codeNodeList(String type) {

		ServiceResult sr = new ServiceResult();
		@SuppressWarnings("unchecked")
		Map<String, List<SysCodeNode>> map3 = (HashMap<String, List<SysCodeNode>>) redisUtils.get(Constants.lIMIT_LIST_CODE);
		sr.setResult(map3.get(type));

		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult addToAreaHot(String branchCode, String[] list) {

		ServiceResult sr = new ServiceResult();

		Map<String, Map<String, SysCodeNode>> codeMap = (Map<String, Map<String, SysCodeNode>>) redisUtils.get(Constants.MAP_CODE);
		SysCodeNode branch = codeMap.get("BranchCode").get(branchCode);
		for (int i = 0; i < list.length; i++) {
			hotProductDao.updateStatus(branchCode, Integer.parseInt(list[i]));
			TbSpHotproduct dbthp = hotProductDao.findByProductIdAndBranchCode(Integer.parseInt(list[i]), branchCode);
			if (null != dbthp && null != dbthp.getId()) {
				dbthp.setStatus(Constants.TRUE);
				TbSpHotproduct addhot = hotProductDao.save(dbthp);
				sr.setResult(addhot);
				SysOperationLog operLog = new SysOperationLog();
				operLog.setIP(Current.IP.get());
				operLog.setLevel("1");
				operLog.setModule("热销产品管理");
				operLog.setOperationTime(new Date());
				operLog.setUserId(Current.userInfo.get().getUserId());
				operLog.setContent("给 " + branch.getCodeCname() + "添加了热销产品-PRODUCT_ID:" + Integer.parseInt(list[i]) + ",-ID:" + addhot.getId());
				operationLogDao.save(operLog);
			} else {
				TbSpHotproduct newdbthp = new TbSpHotproduct();
				newdbthp.setBranchCode(branchCode);
				newdbthp.setProductId(Integer.parseInt(list[i]));
				newdbthp.setStatus(Constants.TRUE);
				TbSpHotproduct addhot = hotProductDao.save(newdbthp);
				sr.setResult(addhot);
				SysOperationLog operLog = new SysOperationLog();
				operLog.setIP(Current.IP.get());
				operLog.setLevel(Constants.TRUE);
				operLog.setModule("热销产品管理");
				operLog.setOperationTime(new Date());
				operLog.setUserId(Current.userInfo.get().getUserId());
				operLog.setContent("给 " + branch.getCodeCname() + "添加了热销产品-PRODUCT_ID:" + Integer.parseInt(list[i]) + ",-ID:" + addhot.getId());
				operationLogDao.save(operLog);
			}
		}
		return sr;
	}

	@Override
	public ServiceResult updateProductSerialNo(Integer id, Integer serialNo) {
		ServiceResult sr = new ServiceResult();
		productDao.updateProductSerialNo(id, serialNo);
		// SysOperationLog operLog = new SysOperationLog();
		// operLog.setIP(Current.IP.get());
		// operLog.setLevel("2");
		// operLog.setModule("热销产品管理");
		// operLog.setOperationTime(new Date());
		// operLog.setUserId(Current.userInfo.get().getUserId());
		// operLog.setContent("修改产品的序号:"+"-ID:"+id);
		// operationLogDao.save(operLog);
		sr.setSuccess();
		return sr;
	}

	@Override

	public ServiceResult findById(Integer id, String refereeId, HttpServletRequest request, String userCode) {
		ServiceResult sr = new ServiceResult();
		Map<String, Object> resMap = Maps.newHashMap();
		TbSpProduct proList = productDao.findByShowId(id);

		if (null != proList) {
			resMap.put("pro", proList);
			sr.setSuccess();
			sr.setResult(resMap);
		} else {
			sr.setFail();
			sr.setResult("没有找到对应的产品！");
			return sr;
		}
		// List<TbSpShare> tbSpList = shareDao.findByShareId(refereeId);
		// if (tbSpList.size() > 0) {
		// TbSpShare tbSp = tbSpList.get(0);
		// // TbSpUser shareUser = userDao.findByUserCode(tbSp.getUserCode());
		// tbSp.setSharinChain(tbSp.getSharinChain() + 1);
		// tbSp.setState(TbSpShare.SHARE_TYPE_VISIT);
		// if (tbSp.getUserCodeChain().indexOf(userCode) == -1 &&
		// tbSp.getUserCodeChain().length() < 500) {
		// tbSp.setUserCodeChain(tbSp.getUserCodeChain() + " " + userCode);
		// }
		// shareDao.save(tbSp);
		// // userDao
		// TbSpUser resUser = new TbSpUser();
		// resUser.setAgrementNo(tbSp.getAgrementNo());
		// resUser.setSaleCode(tbSp.getSaleCode());
		// resUser.setSaleName(tbSp.getSaleName());
		// resUser.setUserCode(tbSp.getUserCode());
		// resUser.setChannelName(tbSp.getChannelName());
		// // resUser.setState(shareUser.getTypeState());
		// resMap.put("agr", resUser);
		// } else {
		// resMap.put("agr", false);
		// }

		// List<TbSpShare> tbSpList = shareDao.findProductShare(refereeId,
		// id.toString());
		// TbSpUser user = new TbSpUser();
		// for (int i = 0; i < tbSpList.size(); i++) {
		// tbSpList.get(i).setState(TbSpShare.SHARE_TYPE_VISIT);
		// tbSpList.get(i).setUserCodeChain(tbSpList.get(i).getUserCodeChain() +
		// ":" + userCode);
		// shareDao.save(tbSpList.get(i));
		// }

		// shareDao
		// 访问统计
		// visitDao
		// TbSpVisit ts = new TbSpVisit();
		// ts.setProductId(id.toString());
		// ts.setProposalNo("");
		// ts.setUpdateTime(new Date());
		// ts.setSessionId(request.getSession().getId());
		// ts.setAccessSource(TbSpVisit.ACCESS_SOURCE_DIRECT);
		// ts.setVisitingTime(new Date());
		// visitDao.save(ts);

		// if (tbSpList.size() > 0) {
		// String queryRefereeId = tbSpList.get(0).getUserCode();
		// if (!StringUtils.isBlank(queryRefereeId) &&
		// !"henghua".equals(queryRefereeId)) {
		// user = userDao.findByUserCode(tbSpList.get(0).getUserCode());
		// }
		// if (!StringUtils.isBlank(tbSpList.get(0).getUserCode()) &&
		// !"henghua".equals(queryRefereeId)) {
		// TbSpUser resUser = new TbSpUser();
		// resUser.setAgrementNo(user.getAgrementNo());
		// resUser.setSaleCode(user.getSaleCode());
		// resUser.setSaleName(user.getSaleName());
		// resUser.setUserCode(user.getUserCode());
		// resMap.put("agr", resUser);
		// } else {
		// resMap.put("agr", false);
		// }
		// } else {
		// resMap.put("agr", false);
		// }

		// if (!StringUtils.isBlank(refereeId)) {
		// user = userDao.findByUserCode(refereeId);
		// }
		// if (!StringUtils.isBlank(refereeId)) {
		// TbSpUser resUser = new TbSpUser();
		// resUser.setAgrementNo(user.getAgrementNo());
		// resUser.setSaleCode(user.getSaleCode());
		// resUser.setSaleName(user.getSaleName());
		// resMap.put("agr", resUser);
		// } else {
		// resMap.put("agr", false);
		// }

		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult addPlans(TbSpProduct tbSpProduct) {
		ServiceResult sr = new ServiceResult();
		String productId = String.valueOf(tbSpProduct.getId());
		List<Integer> dbPlanids = spPlanDao.findIdsByProductId(productId);
		List<Integer> reqPlanids = Lists.newArrayList();
		List<TbSpPlan> savePlan = tbSpProduct.getTbSpPlans();
		spPlanDao.deleteByProduct(productId);
		for (TbSpPlan p : savePlan) {
			if (null != p.getId()) {
				log.info("修改的计划ID==》：" + p.getId());
				reqPlanids.add(p.getId());
			}
			p.setProductId(productId);
			log.info("------content------" + p.getClauseContent());
			TbSpPlan plan = spPlanDao.save(p);
			SysOperationLog operLog = new SysOperationLog();
			operLog.setIP(Current.IP.get());
			operLog.setLevel("1");
			operLog.setModule("产品-计划");
			operLog.setOperationTime(new Date());
			operLog.setUserId(Current.userInfo.get().getUserId());
			operLog.setContent("给ID为" + productId + "的产品添加计划," + "计划的-ID:" + plan.getId());
			operationLogDao.save(operLog);
		}
		for (Integer id : dbPlanids) {
			if (!reqPlanids.contains(id)) {
				log.info("删除的计划ID--》：" + id);
				SysOperationLog operLog = new SysOperationLog();
				operLog.setIP(Current.IP.get());
				operLog.setLevel("3");
				operLog.setModule("产品-计划");
				operLog.setOperationTime(new Date());
				operLog.setUserId(Current.userInfo.get().getUserId());
				operLog.setContent("删除" + productId + "的产品添加计划," + "计划的-ID:" + id);
				spPlanDao.deleteById(id);
			}
		}
		// 更新计划缓存
		Map<String, List<TbSpPlan>> planMap = (Map<String, List<TbSpPlan>>) redisUtils.get(Constants.PLAN_INFO);
		List<TbSpPlan> plans = spPlanDao.findByProductId(productId);
		planMap.put(productId, plans);
		redisUtils.set(Constants.PLAN_INFO, planMap);
		sr.setSuccess();
		return sr;
	}

	@Override
	public ServiceResult planList(Integer productId) {
		ServiceResult sr = new ServiceResult();
		sr.setResult(spPlanDao.findAllByProductId(String.valueOf(productId)));
		return sr;
	}

	@Override
	public ServiceResult querySalePlan(String productId, String userCode) {
		ServiceResult sr = new ServiceResult();

		Map<String, List<TbSpPlan>> planMap = (Map<String, List<TbSpPlan>>) redisUtils.get(Constants.PLAN_INFO);
		List<TbSpPlan> spPlans = planMap.get(productId);
		// List<TbSpPlan> spPlans = spPlanDao.findByProductId(productId);
		if (null == spPlans) {
			spPlans = spPlanDao.findByProductId(productId);
		}
		if (spPlans.size() > 0) {
			sr.setSuccess();
			sr.setResult(spPlans);
		} else {
			sr.setFail();
			sr.setResult("每页配置对应的计划！");
		}
		return sr;
//		ServiceResult sr = new ServiceResult();
//
//		Map<String, List<TbSpPlan>> planMap = (Map<String, List<TbSpPlan>>) redisUtils.get(Constants.PLAN_INFO);
//		List<TbSpPlan> spPlans = planMap.get(productId);
//		// List<TbSpPlan> spPlans = spPlanDao.findByProductId(productId);
//		if (null == spPlans) {
//			spPlans = spPlanDao.findByProductId(productId);
//		}
//		if (spPlans.size() > 0) {
//			Map<String,Object> resMap = new HashMap<String,Object>();
//			List<Map<String, Object>> list=null;
//			TbSpPlan plan = spPlans.get(0);
//			String sql ="select group_concat(DISTINCT(p.PROPSCODE)) as propscode from prpdplansub p where p.PLANCODE=? ";
//			list = readJdbcTemplate.queryForList(sql, new Object[] { plan.getPlanId() });
//			resMap.put("planList", spPlans);
//			resMap.put("propscode",list);
//			sr.setSuccess();
//			sr.setResult(resMap);
//		} else {
//			sr.setFail();
//			sr.setResult("没有配置对应的计划！");
//		}
//		return sr;
	}

	@Override
	public ServiceResult productByRisk(String riskCode) {
		ServiceResult sr = new ServiceResult();
		if (StringUtils.isNotEmpty(riskCode)) {
			List<TbSpProduct> pros = productDao.findByRiskCode(riskCode);
			sr.setResult(pros);
		} else {
			List<TbSpProduct> pros = productDao.findAllProduct();
			sr.setResult(pros);
		}
		return sr;
	}

	@Override
	public ServiceResult getExclusive(Integer productId, String userCode, String userName, String branchCode, String agrementNo, String isIn,
			int pageNumber, int pageSize) {
		ServiceResult sr = new ServiceResult();
		Sort sort = new Sort(Direction.ASC, "id");

		sr.setResult(userDao.findAll(new Specification<TbSpUser>() {
			@Override
			public Predicate toPredicate(Root<TbSpUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

				List<Predicate> predicate = new ArrayList<Predicate>();

				if (userCode != null) {
					log.info(userCode);
					predicate.add(cb.like(root.get("userCode").as(String.class), "%" + userCode + "%"));
				}
				if (StringUtils.isNotEmpty(userName)) {
					log.info(userName);
					predicate.add(cb.like(root.get("userName").as(String.class), "%" + userName + "%"));
				}
				if (StringUtils.isNotEmpty(agrementNo)) {
					log.info(agrementNo);
					predicate.add(cb.like(root.get("agrementNo").as(String.class), "%" + agrementNo + "%"));
				}
				if (StringUtils.isNotEmpty(branchCode)) {
					log.info("branchCode------------" + branchCode);
					predicate.add(cb.equal(root.get("branchCode").as(String.class), branchCode));
				}
				if (StringUtils.isNotEmpty(isIn) && "no".equals(isIn)) {
					log.info("no");
					List<TbSpUser> applicant = userDao.findNotExclusiveUser(productId);
					In<String> in = cb.in(root.get("userCode").as(String.class));
					if (null != applicant && applicant.size() != 0) {
						for (TbSpUser ts : applicant) {
							in.value(ts.getUserCode());
						}
					}
					predicate.add(in);
				} else {
					log.info("yes");
					List<TbSpExclusiveProduct> applicant = exclusiveProductDao.findByProductId(productId);
					In<String> in = cb.in(root.get("userCode").as(String.class));
					if (null != applicant && applicant.size() != 0) {
						for (TbSpExclusiveProduct ts : applicant) {
							in.value(ts.getUserCode());
						}
					} else {
						in.value(" ");
					}
					predicate.add(in);
				}
				predicate.add(cb.equal(root.get("state").as(String.class), "1"));
				predicate.add(cb.equal(root.get("storeFlag").as(String.class), "1"));
				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		}, PageRequest.of(pageNumber - 1, pageSize, sort)));

		return sr;
	}

	@Override
	public ServiceResult setExclusive(Integer productId, String isExclusive, String[] codes) {
		ServiceResult sr = new ServiceResult();
		if ("true".equals(isExclusive)) {
			for (int i = 0; i < codes.length; i++) {
				TbSpExclusiveProduct tsep = new TbSpExclusiveProduct();
				tsep.setProductId(productId);
				tsep.setUserCode(codes[i]);
				exclusiveProductDao.save(tsep);
			}
		} else if ("false".equals(isExclusive)) {
			// 取消专属人员
			for (int i = 0; i < codes.length; i++) {
				exclusiveProductDao.deleteByPidAndUcode(productId, codes[i]);
				storeProductDao.deleteByProId(productId, codes[i]);
			}
		}
		return sr;
	}

}
